#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
劳动赔偿计算器

功能：
- 支持10种劳动纠纷赔偿类型计算
- 支持17个主要城市的地区差异化计算
- 提供详细的计算过程和法律依据
- 数据验证和错误处理

"""

import math
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional, Union
import json

class LaborCompensationCalculator:
    """劳动赔偿计算器主类"""
    
    def __init__(self):
        """初始化计算器"""
        self.city_data = self._load_city_data()
        self.calculation_results = []
    
    def _load_city_data(self) -> Dict:
        """加载城市数据配置"""
        return {
            "北京市": {
                "social_avg_salary": 16821.25,
                "compensation_cap": 50463.75,
                "maternity_days": 128,
                "calculation_base": "法人单位从业人员平均工资",
                "special_rules": "采用法人单位从业人员平均工资，不使用全口径标准"
            },
            "上海市": {
                "social_avg_salary": 12183,
                "compensation_cap": 36549,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "2008年前后分段计算，加班工资原则上不计入基数"
            },
            "广州市": {
                "social_avg_salary": 9917,
                "compensation_cap": 29751,
                "maternity_days": 178,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "应得工资概念明确，年终奖不计入基数"
            },
            "深圳市": {
                "social_avg_salary": 13730,
                "compensation_cap": 41190,
                "maternity_days": 178,
                "calculation_base": "在岗职工平均工资",
                "special_rules": "采用在岗职工平均工资，正常工作状态下的平均工资"
            },
            "杭州市": {
                "social_avg_salary": 10389,
                "compensation_cap": 31167,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按浙江省规定，加班工资是否计入存在争议"
            },
            "成都市": {
                "social_avg_salary": 8875,
                "compensation_cap": 26625,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "加班工资需证明常规性才计入基数"
            },
            "天津市": {
                "social_avg_salary": 9016,
                "compensation_cap": 27048,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按天津市规定，加班工资计入基数"
            },
            "重庆市": {
                "social_avg_salary": 8533,
                "compensation_cap": 25599,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按重庆市规定执行"
            },
            "西安市": {
                "social_avg_salary": 7892,
                "compensation_cap": 23676,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按陕西省规定执行"
            },
            "武汉市": {
                "social_avg_salary": 8234,
                "compensation_cap": 24702,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按湖北省规定执行"
            },
            "南京市": {
                "social_avg_salary": 9567,
                "compensation_cap": 28701,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按江苏省规定执行"
            },
            "苏州市": {
                "social_avg_salary": 10234,
                "compensation_cap": 30702,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按江苏省规定执行"
            },
            "青岛市": {
                "social_avg_salary": 8456,
                "compensation_cap": 25368,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按山东省规定执行"
            },
            "大连市": {
                "social_avg_salary": 7823,
                "compensation_cap": 23469,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按辽宁省规定执行"
            },
            "厦门市": {
                "social_avg_salary": 9123,
                "compensation_cap": 27369,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按福建省规定执行"
            },
            "长沙市": {
                "social_avg_salary": 7654,
                "compensation_cap": 22962,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按湖南省规定执行"
            },
            "全国通用": {
                "social_avg_salary": 8000,
                "compensation_cap": 24000,
                "maternity_days": 158,
                "calculation_base": "全口径城镇单位就业人员平均工资",
                "special_rules": "按国家标准执行"
            }
        }
    
    def calculate_economic_compensation(self, monthly_salary: float, work_years: float, city: str = "全国通用") -> Dict:
        """计算经济补偿金（N）
        
        Args:
            monthly_salary: 月平均工资
            work_years: 工作年限
            city: 所在城市
            
        Returns:
            计算结果字典
        """
        city_info = self.city_data.get(city, self.city_data["全国通用"])
        compensation_cap = city_info["compensation_cap"]
        
        # 计算补偿月数
        if work_years == 0:
            compensation_months = 0
        elif work_years < 0.5:
            compensation_months = 0.5
        elif work_years < 1:
            compensation_months = 1
        else:
            compensation_months = math.ceil(work_years)
        
        # 应用工资上限
        effective_salary = min(monthly_salary, compensation_cap)
        
        # 应用年限上限（高收入者）
        if monthly_salary > compensation_cap:
            compensation_months = min(compensation_months, 12)
        
        compensation = effective_salary * compensation_months
        
        return {
            "type": "经济补偿金（N）",
            "amount": compensation,
            "details": {
                "monthly_salary": monthly_salary,
                "effective_salary": effective_salary,
                "work_years": work_years,
                "compensation_months": compensation_months,
                "city": city,
                "compensation_cap": compensation_cap
            },
            "formula": f"经济补偿金 = {effective_salary} × {compensation_months} = {compensation}",
            "legal_basis": "《劳动合同法》第四十七条",
            "notes": [
                f"工作年限{work_years}年，补偿{compensation_months}个月",
                f"月工资{monthly_salary}元，{'超过' if monthly_salary > compensation_cap else '未超过'}当地三倍社平工资上限",
                f"适用{city}标准，三倍社平工资上限为{compensation_cap}元"
            ]
        }
    
    def calculate_severance_pay(self, monthly_salary: float, work_years: float, city: str = "全国通用") -> Dict:
        """计算赔偿金（2N）"""
        economic_compensation = self.calculate_economic_compensation(monthly_salary, work_years, city)
        severance_amount = economic_compensation["amount"] * 2
        
        return {
            "type": "赔偿金",
            "amount": severance_amount,
            "details": {
                "economic_compensation": economic_compensation["amount"],
                "multiplier": 2
            },
            "formula": f"赔偿金 = 经济补偿金 × 2 = {economic_compensation['amount']} × 2 = {severance_amount}",
            "legal_basis": "《劳动合同法》第八十七条",
            "notes": [
                "适用于用人单位违法解除或终止劳动合同",
                "基于经济补偿金计算，按两倍标准执行"
            ]
        }
    
    def calculate_double_salary(self, monthly_salary: float, unsigned_months: int) -> Dict:
        """计算双倍工资"""
        double_salary = monthly_salary * unsigned_months
        
        return {
            "type": "双倍工资",
            "amount": double_salary,
            "details": {
                "monthly_salary": monthly_salary,
                "unsigned_months": unsigned_months
            },
            "formula": f"双倍工资 = {monthly_salary} × {unsigned_months} = {double_salary}",
            "legal_basis": "《劳动合同法》第八十二条",
            "notes": [
                "适用于用工超过一个月不满一年未签书面劳动合同",
                f"未签合同期间{unsigned_months}个月，按月工资{monthly_salary}元计算"
            ]
        }
    
    def calculate_overdue_salary_compensation(self, overdue_amount: float) -> Dict:
        """计算拖欠工资赔偿"""
        compensation = overdue_amount * 1.5
        
        return {
            "type": "拖欠工资赔偿",
            "amount": compensation,
            "details": {
                "overdue_amount": overdue_amount,
                "compensation_rate": 0.5
            },
            "formula": f"拖欠工资赔偿 = {overdue_amount} + {overdue_amount} × 50% = {compensation}",
            "legal_basis": "《劳动合同法》第八十五条",
            "notes": [
                "包含拖欠工资本金和50%的赔偿金",
                f"拖欠工资本金{overdue_amount}元"
            ]
        }
    
    def calculate_work_injury_compensation(self, medical_expenses: float, disability_level: int, monthly_salary: float) -> Dict:
        """计算工伤医疗赔偿"""
        # 一次性伤残补助金标准（月数）
        disability_months = {
            1: 27, 2: 25, 3: 23, 4: 21, 5: 18,
            6: 16, 7: 13, 8: 11, 9: 9, 10: 7
        }
        
        if disability_level not in disability_months:
            raise ValueError("伤残等级必须在1-10级之间")
        
        months = disability_months[disability_level]
        disability_compensation = monthly_salary * months
        total_compensation = medical_expenses + disability_compensation
        
        return {
            "type": "工伤医疗赔偿",
            "amount": total_compensation,
            "details": {
                "medical_expenses": medical_expenses,
                "disability_level": disability_level,
                "disability_months": months,
                "disability_compensation": disability_compensation,
                "monthly_salary": monthly_salary
            },
            "formula": f"工伤医疗赔偿 = {medical_expenses} + {monthly_salary} × {months} = {total_compensation}",
            "legal_basis": "《工伤保险条例》第三十条、第三十五条、第三十六条、第三十七条",
            "notes": [
                f"{disability_level}级伤残，一次性伤残补助金{months}个月本人工资",
                f"医疗费用{medical_expenses}元，伤残补助金{disability_compensation}元"
            ]
        }
    
    def calculate_probation_extension_compensation(self, probation_salary: float, regular_salary: float, excess_days: int) -> Dict:
        """计算试用期违法延长赔偿"""
        # 按月计算工资差额，然后按天分摊
        monthly_difference = regular_salary - probation_salary
        total_compensation = monthly_difference * excess_days / 30
        
        return {
            "type": "试用期违法延长赔偿",
            "amount": total_compensation,
            "details": {
                "probation_salary": probation_salary,
                "regular_salary": regular_salary,
                "monthly_difference": monthly_difference,
                "excess_days": excess_days
            },
            "formula": f"赔偿 = ({regular_salary} - {probation_salary}) × {excess_days} ÷ 30 = {total_compensation}",
            "legal_basis": "《劳动合同法》第八十三条",
            "notes": [
                f"工资差额{monthly_difference}元/月，超期{excess_days}天",
                "按工资差额的日标准计算"
            ]
        }
    
    def calculate_annual_leave_compensation(self, monthly_salary: float, unused_days: int) -> Dict:
        """计算未休年假工资"""
        daily_salary = monthly_salary / 21.75
        compensation = daily_salary * unused_days * 3  # 300%
        
        return {
            "type": "未休年假工资",
            "amount": compensation,
            "details": {
                "monthly_salary": monthly_salary,
                "daily_salary": daily_salary,
                "unused_days": unused_days,
                "compensation_rate": 3.0
            },
            "formula": f"未休年假工资 = {monthly_salary} ÷ 21.75 × {unused_days} × 300% = {compensation}",
            "legal_basis": "《职工带薪年休假条例》第三条、第五条",
            "notes": [
                f"未休年假{unused_days}天，按300%标准计算",
                f"日工资{daily_salary:.2f}元"
            ]
        }
    
    def calculate_maternity_allowance_difference(self, monthly_salary: float, maternity_allowance: float, maternity_months: float) -> Dict:
        """计算生育津贴/产假工资差额"""
        if monthly_salary <= maternity_allowance:
            difference = 0
            notes = ["生育津贴高于或等于本人工资，无需补差"]
        else:
            difference = (monthly_salary - maternity_allowance) * maternity_months
            notes = [f"本人工资高于生育津贴，需补差{difference}元"]
        
        return {
            "type": "生育津贴/产假工资差额",
            "amount": difference,
            "details": {
                "monthly_salary": monthly_salary,
                "maternity_allowance": maternity_allowance,
                "maternity_months": maternity_months,
                "monthly_difference": monthly_salary - maternity_allowance
            },
            "formula": f"差额 = ({monthly_salary} - {maternity_allowance}) × {maternity_months} = {difference}",
            "legal_basis": "《女职工劳动保护特别规定》第八条",
            "notes": notes
        }
    
    def calculate_overtime_compensation(self, monthly_salary: float, weekday_hours: float = 0, weekend_hours: float = 0, holiday_hours: float = 0) -> Dict:
        """计算加班费"""
        hourly_salary = monthly_salary / 21.75 / 8
        
        weekday_compensation = hourly_salary * 1.5 * weekday_hours
        weekend_compensation = hourly_salary * 2 * weekend_hours
        holiday_compensation = hourly_salary * 3 * holiday_hours
        
        total_compensation = weekday_compensation + weekend_compensation + holiday_compensation
        
        return {
            "type": "加班费",
            "amount": total_compensation,
            "details": {
                "monthly_salary": monthly_salary,
                "hourly_salary": hourly_salary,
                "weekday_hours": weekday_hours,
                "weekend_hours": weekend_hours,
                "holiday_hours": holiday_hours,
                "weekday_compensation": weekday_compensation,
                "weekend_compensation": weekend_compensation,
                "holiday_compensation": holiday_compensation
            },
            "formula": f"加班费 = {hourly_salary:.2f} × (1.5×{weekday_hours} + 2×{weekend_hours} + 3×{holiday_hours}) = {total_compensation}",
            "legal_basis": "《劳动法》第四十四条",
            "notes": [
                f"时薪{hourly_salary:.2f}元",
                f"工作日加班{weekday_hours}小时，补偿{weekday_compensation:.2f}元",
                f"休息日加班{weekend_hours}小时，补偿{weekend_compensation:.2f}元",
                f"法定节假日加班{holiday_hours}小时，补偿{holiday_compensation:.2f}元"
            ]
        }
    
    def calculate_illegal_transfer_compensation(self, original_salary: float, new_salary: float, reduction_months: int, work_years: float) -> Dict:
        """计算违法调岗降薪赔偿"""
        salary_loss = (original_salary - new_salary) * reduction_months
        severance_compensation = original_salary * math.ceil(work_years) * 2
        total_compensation = salary_loss + severance_compensation
        
        return {
            "type": "违法调岗降薪赔偿",
            "amount": total_compensation,
            "details": {
                "original_salary": original_salary,
                "new_salary": new_salary,
                "salary_difference": original_salary - new_salary,
                "reduction_months": reduction_months,
                "salary_loss": salary_loss,
                "work_years": work_years,
                "severance_compensation": severance_compensation
            },
            "formula": f"赔偿 = ({original_salary} - {new_salary}) × {reduction_months} + {original_salary} × {math.ceil(work_years)} × 2 = {total_compensation}",
            "legal_basis": "《劳动合同法》第三十八条、第八十七条",
            "notes": [
                f"工资差额损失{salary_loss}元",
                f"解除合同赔偿金{severance_compensation}元",
                f"降薪{reduction_months}个月，工作{work_years}年"
            ]
        }
    
    def get_city_list(self) -> List[str]:
        """获取支持的城市列表"""
        return list(self.city_data.keys())
    
    def get_city_info(self, city: str) -> Dict:
        """获取城市信息"""
        return self.city_data.get(city, self.city_data["全国通用"])
    
    def validate_input(self, value: Union[int, float], min_value: float = 0, max_value: float = None, field_name: str = "数值") -> bool:
        """输入验证"""
        if not isinstance(value, (int, float)):
            raise ValueError(f"{field_name}必须是数字")
        if value < min_value:
            raise ValueError(f"{field_name}不能小于{min_value}")
        if max_value is not None and value > max_value:
            raise ValueError(f"{field_name}不能大于{max_value}")
        return True
    
    def generate_calculation_report(self, results: List[Dict]) -> str:
        """生成计算报告"""
        report = "\n" + "="*60 + "\n"
        report += "劳动赔偿计算报告\n"
        report += "="*60 + "\n"
        report += f"生成时间：{datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')}\n\n"
        
        total_amount = 0
        for i, result in enumerate(results, 1):
            report += f"{i}. {result['type']}\n"
            report += f"   计算结果：{result['amount']:,.2f}元\n"
            report += f"   计算公式：{result['formula']}\n"
            report += f"   法律依据：{result['legal_basis']}\n"
            if result.get('notes'):
                report += "   说明：\n"
                for note in result['notes']:
                    report += f"     - {note}\n"
            report += "\n"
            total_amount += result['amount']
        
        report += "-"*60 + "\n"
        report += f"总计赔偿金额：{total_amount:,.2f}元\n"
        report += "-"*60 + "\n"
        
        return report


if __name__ == "__main__":
    # 示例使用
    calculator = LaborCompensationCalculator()
    
    print("劳动赔偿计算器 v1.0")
    print("支持的城市：", ", ".join(calculator.get_city_list()))
    
    # 示例计算
    results = []
    
    # 经济补偿金计算示例
    result1 = calculator.calculate_economic_compensation(
        monthly_salary=15000,
        work_years=3.5,
        city="北京市"
    )
    results.append(result1)
    
    # 加班费计算示例
    result2 = calculator.calculate_overtime_compensation(
        monthly_salary=8000,
        weekday_hours=20,
        weekend_hours=16,
        holiday_hours=8
    )
    results.append(result2)
    
    # 生成报告
    report = calculator.generate_calculation_report(results)
    print(report)